package cn.qingyun.gis.modules.takeaway.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.modules.express.config.Exception.CustomExceptionHandler;
import cn.qingyun.gis.modules.express.entity.ExpressRegion;
import cn.qingyun.gis.modules.express.service.IExpressRegionService;
import cn.qingyun.gis.modules.express.util.SyncTool;
import cn.qingyun.gis.modules.init.system.entity.SysLog;
import cn.qingyun.gis.modules.init.system.mapper.SysLogMapper;
import cn.qingyun.gis.modules.takeaway.entity.TakeawayProofread;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayDataHandleService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayProofreadService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.io.WKTReader;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class ITakeawayDataHandleServiceImpl implements ITakeawayDataHandleService {
    @Resource
    private IExpressRegionService iExpressRegionService;
    @Resource
    private ITakeawayProofreadService iTakeawayProofreadService;
    @Resource
    private SysLogMapper sysLogMapper;
    @Resource
    private CustomExceptionHandler customExceptionHandler;

    @Override
    public void matchGrid() {
        AtomicInteger n = new AtomicInteger();

        // 获取微网格级别业务区划数据
        LambdaQueryWrapper<ExpressRegion> miroGridWrapper = new QueryWrapper<ExpressRegion>().lambda().eq(ExpressRegion::getLevel, "5").ne(ExpressRegion::getGeometry, "");
        List<ExpressRegion> miroGridTotal = iExpressRegionService.list(miroGridWrapper);
        // 获取网格级别业务区划数据
        LambdaQueryWrapper<ExpressRegion> gridWrapper = new QueryWrapper<ExpressRegion>().lambda().eq(ExpressRegion::getLevel, "4").ne(ExpressRegion::getGeometry, "");
        List<ExpressRegion> gridTotal = iExpressRegionService.list(gridWrapper);
        // 获取区县级别业务区划数据
        LambdaQueryWrapper<ExpressRegion> districtsWrapper = new QueryWrapper<ExpressRegion>().lambda().eq(ExpressRegion::getLevel, "3").ne(ExpressRegion::getGeometry, "");
        List<ExpressRegion> districtsTotal = iExpressRegionService.list(districtsWrapper);
        // 获取地市级别业务区划数据
        LambdaQueryWrapper<ExpressRegion> cityWrapper = new QueryWrapper<ExpressRegion>().lambda().eq(ExpressRegion::getLevel, "2").ne(ExpressRegion::getGeometry, "");
        List<ExpressRegion> cityTotal = iExpressRegionService.list(cityWrapper);

        // 计算全量外卖信息数据条数
        int count = iTakeawayProofreadService.count();
        int pages = (count / 1000) + 1;

        long start = System.currentTimeMillis();
        // 根据数据总量划分数据块并启动多线程
        SyncTool.doSync(pages, i -> {
            Page<TakeawayProofread> page = new Page<>(i, 1000);
            List<TakeawayProofread> proofreads = iTakeawayProofreadService.page(page, null).getRecords();
            List<TakeawayProofread> updateRecords = Lists.newArrayList();

            for (TakeawayProofread data : proofreads) {
                log.debug(String.format("====================开始匹配外卖 %s====================", data.getId()));

                double lon = 0;
                double lat = 0;
                // 如果原始经纬度不为空
                if (ObjectUtil.isNotEmpty(data.getLon()) && ObjectUtil.isNotEmpty(data.getLat())) {
                    lon = data.getLon().doubleValue();
                    lat = data.getLat().doubleValue();
                }
                // 如果勘误经纬度不为空
                if (ObjectUtil.isNotEmpty(data.getKwLon()) && ObjectUtil.isNotEmpty(data.getKwLat())) {
                    lon = data.getKwLon().doubleValue();
                    lat = data.getKwLat().doubleValue();
                }
                try {
                    // 需要匹配经纬度都不为0
                    if ((lat != 0) && (lon != 0)) {

                        // 创建点对象
                        Point point = new GeometryFactory().createPoint(new Coordinate(data.getLon().doubleValue(), data.getLat().doubleValue()));
                        // 创建边界对象
                        Geometry geometry = null;
                        // 1.进行微网格匹配
                        for (ExpressRegion miroGridData : miroGridTotal) {
                            // 创建面对象

                            geometry = new WKTReader().read(miroGridData.getGeometry());
                            // 微网格匹配成功
                            if (geometry.contains(point)) {
                                data.setMicroGridId(miroGridData.getCode());
                                data.setMicroGridName(miroGridData.getName());
                                break;
                            }

                        }
                        // 2.进行网格匹配
                        for (ExpressRegion gridData : gridTotal) {
                            // 创建面对象

                            geometry = new WKTReader().read(gridData.getGeometry());

                            if (geometry.contains(point)) {
                                data.setGridId(gridData.getCode());
                                data.setGridName(gridData.getName());
                                break;
                            }


                        }
                        // 3.进行区县匹配
                        for (ExpressRegion disData : districtsTotal) {
                            // 创建面对象

                            geometry = new WKTReader().read(disData.getGeometry());

                            if (geometry.contains(point)) {
                                data.setRegionDistrictsCode(disData.getCode());
                                data.setRegionDistricts(disData.getName());
                                break;
                            }

                        }
                        // 4.进行地市匹配
                        for (ExpressRegion cityData : cityTotal) {
                            // 创建面对象

                            geometry = new WKTReader().read(cityData.getGeometry());
                            // 匹配地市
                            if (geometry.contains(point)) {
                                data.setRegionCityCode(cityData.getCode());
                                data.setRegionCity(cityData.getName());
                                break;
                            }

                        }
                    }
                    synchronized (this) {
                        n.incrementAndGet();
                        log.debug(String.format("=========== 当前匹配进度为%s / %s ===========", n, count));
                    }
                    updateRecords.add(data);
                } catch (Exception e) {
                    customExceptionHandler.handleException(String.format("外卖站点-%s,入格失败！|报错：%s", data.getPoiName(), e.getMessage()), start);
                }
            }
            // 批量导入匹配之后数据
            iTakeawayProofreadService.updateBatchById(updateRecords);

        });

        log.debug(String.format("外卖数据匹配网格完成，====一共处理%s外卖数据====", count));
        long finish = System.currentTimeMillis();

        SysLog sysLog = new SysLog();
        sysLog.setLogContent("外卖数据匹配成功");
        sysLog.setCreateTime(DateUtil.date());
        sysLog.setLogType(3); //
        sysLog.setCreateBy("system");
        sysLog.setCostTime(finish - start);
        sysLog.setUserid("匹配任务");
        sysLogMapper.insert(sysLog);
    }
}
